const fs = require('fs')
const path = require('path')
const vm = require('vm')


//  值类型时 一直100不变  引用类型时 100递增
// setInterval(() => {
//     console.log(require('./a'))
// }, 1000)


//----------------commonjs实现

function Module(id) {
    this.id = id
    this.exports = {} // 模块最终的导出结果


}
Module._cache = {} // 用来缓存

Module.prototype._load = function () { // 加载模块 读取文件内容
    let extensions = path.extname(this.id) // 获取文件后缀名
    Module._extensions[extensions](this)
}

Module._extensions = {
    '.js'(module) {
        let script = fs.readFileSync(module.id, 'utf8')
        let template = `(function(exports,module,require,__filename,__dirname){${script}})`
        let compileFunction = vm.runInThisContext(template);
        // console.log(compileFunction.toString())
        let exports = module.exports
        let thisValue = exports // this === export === module.export === {}
        let filename = module.id
        let dirname = path.dirname(filename)
        compileFunction.call(thisValue, exports, module, myRequire, filename, dirname)

    },
    '.json'(module) {
        let jsonStr = fs.readFileSync(module.id, 'utf8')
        module.exports = JSON.parse(jsonStr)
    }
}


Module._resolveFilename = function (filename) {  // 转化为绝对路径
    const filePath = path.resolve(__dirname, filename)
    let exists = fs.existsSync(filePath) // 是否为一个文件
    if (exists) return exists
    // 文件没有后缀名时
    let keys = Reflect.ownKeys(Module._extensions); //  等同于 Object.keys
    // console.log(keys) // ['.js','.json']  
    for (let i = 0; i < keys.length; i++) {
        let newPath = filePath + keys[i]
        if (fs.existsSync(newPath)) return newPath // 手动为文件拼接后缀并且查看是否路径是否可以匹配到文件
    }
    throw new Error('没有匹配到的文件')
}



function myRequire(filename) {
    let filePath = Module._resolveFilename(filename)
    // console.log(filePath) // c:\Users\12288\Desktop\ZF-CODE\node\common\a.js
    let exists = Module._cache[filePath]
    if (exists) { // 如果文件被缓存过
        return exists.exports
    }

    let module = new Module(filePath) // 创造一个模块
    Module._cache[filePath] = module // 将模块以绝对路径为key写进缓存
    module._load()
    return module.exports
}

// console.log(myRequire('./b')) // {b:100}
console.log(myRequire('./c')) // { name: 'ljp' }